/*
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *
 *  Authors:
 *  	Albert Marieges Garcia
 *  	Álex Pardo Fernández
 *  	Enric Mayas Márquez
 *  	Juan Carlos Calvo Tejedor
 *  	Marc Gironés Dezsényi
 *  
 *  Contact:
 *  	bcn.tours.android@gmail.com
 *  Webpage:
 *  	bcntours.co.cc
 *
 */
package com.BCNTours.Maps.Vista;

import java.util.ArrayList;
import java.util.List;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;

import com.BCNTours.R;
import com.BCNTours.AR.Utils.ARLocationManager;
import com.BCNTours.Info.Vista.InfoActivity;
import com.BCNTours.Maps.Utils.CalcRoute;
import com.BCNTours.Maps.Utils.DetailedRoute;
import com.BCNTours.Maps.Utils.DrawRoute;
import com.BCNTours.Maps.Utils.OverlayManager;
import com.BCNTours.Maps.Utils.RouteListParser;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

/**
 * Shows a mapview which displays the route to follow from the current location from a destination. 
 */
public class MapRoute extends MapActivity{

	private Location myLocation;
	private List<Overlay> mapOverlays;
	private Bundle extras;
	private Drawable drawable;
	private OverlayManager startManager;
	private OverlayManager desitinationManager;
	private GeoPoint start;
	private GeoPoint destination;
	private MapView mapView;
	private MapController mc;
	private Toast msg;
	

	/**
	 * Class constructor
	 */
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        ConnectivityManager cm = (ConnectivityManager) getApplicationContext().getSystemService( Context.CONNECTIVITY_SERVICE );
        if(cm.getActiveNetworkInfo() == null){
        
        	initializationWifi();
        }
        
        setContentView(R.layout.maps);
        
        extras = getIntent().getExtras();
        
        mapView = (MapView) findViewById(R.id.mapview);
        mapView.setBuiltInZoomControls(true);
        
        mc = mapView.getController();
        if(isLocationAvailable()){
        	initializationLocation();
        }
        GeoPoint center = new GeoPoint((int)(myLocation.getLatitude()*1000000),(int)(myLocation.getLongitude()*1000000));
        mc.setCenter(center);
        mc.setZoom(13);
        
        mapOverlays = mapView.getOverlays();
        drawable = this.getResources().getDrawable(R.drawable.inici);
        startManager = new OverlayManager(drawable, this, false);
        drawable = this.getResources().getDrawable(R.drawable.desti);
        desitinationManager = new OverlayManager(drawable, this, false);
        
        Thread calcRoute = new Thread() {
    		
    		@Override
    		public void run() {
    			super.run();
    			double latitude = extras.getDouble("lat");
    	    	double longitude = extras.getDouble("long");
    	    	String name = extras.getString("nom");
    	    	OverlayItem item;
    	    	//Current location
    	        start = new GeoPoint((int)(myLocation.getLatitude()*1000000),(int)(myLocation.getLongitude()*1000000));
    	        item = new OverlayItem(start, "Inici Ruta", "");
    			startManager.addOverlay(item);
    	        //Destination
    	        destination = new GeoPoint((int)latitude,(int)longitude);
    	        item = new OverlayItem(destination, name, "");
    			desitinationManager.addOverlay(item);
    	        DrawPath(start, destination, Color.GREEN, mapView);
    			mapOverlays.add(startManager);
    			mapOverlays.add(desitinationManager);
    			startManager.draw();
    			desitinationManager.draw();
    			msg.cancel();
    			
    		}
    	};
    	
    	try {
			InfoActivity.loading.dismiss();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	msg = Toast.makeText(getApplicationContext(), R.string.msgCalcRoute, 1000);
    	msg.show();
    	calcRoute.run();
    	
    }
	
	/**
     * Create a menu of the activity
     */
    public boolean onCreateOptionsMenu(Menu menu){
    	MenuInflater mi = getMenuInflater();
    	mi.inflate(R.menu.route_menu , menu);
    	return true;
    }
    
    /**
     * Listener from the menu
     */
    public boolean onOptionsItemSelected (MenuItem item){
    	switch (item.getItemId()){
    		//Distance menu
    		case R.id.route_menu_list:
    			ArrayList<String> tmp = new RouteListParser().getRoute(start, destination);
    			Intent i = new Intent(getApplicationContext(), DetailedRoute.class);
    			i.putExtra("instr", tmp);
    			startActivity(i);
    			break;
    		
    		default:
    			Toast.makeText(getApplicationContext(), "Menu error!", Toast.LENGTH_LONG);
    			break;
    			
    	}
    	return false;
    }
	
	/**
	 * Draws the route to follow to reach the destination point for the current location of the user.
	 * @param src User's current location
	 * @param dest User's destination
	 * @param color Color to draw the route with, green is always used
	 * @param mMapView01 MapView where the route will be drawn
	 */
	private void DrawPath(GeoPoint src,GeoPoint dest, int color, MapView mMapView01){
		// connect to map web service
		CalcRoute calculator = new CalcRoute();
		String[] pairs = calculator.getRoute(src, dest);
		String[] lngLat = pairs[0].split(","); // lngLat[0]=longitude lngLat[1]=latitude lngLat[2]=height
		// source point
		GeoPoint startGP = new GeoPoint((int)(Double.parseDouble(lngLat[1])*1E6),(int)(Double.parseDouble(lngLat[0])*1E6));
		mMapView01.getOverlays().add(new DrawRoute(startGP,startGP,1));
		GeoPoint gp1;
		GeoPoint gp2 = startGP;
			for(int i=1;i<pairs.length;i++){  // the last one would be crash
			lngLat = pairs[i].split(",");
			gp1 = gp2;
			gp2 = new GeoPoint((int)(Double.parseDouble(lngLat[1])*1E6),(int)(Double.parseDouble(lngLat[0])*1E6));
			mMapView01.getOverlays().add(new DrawRoute(gp1,gp2,2,color));
			Log.d("xxx","pair:" + pairs[i]);
			}
		mMapView01.getOverlays().add(new DrawRoute(dest,dest, 3)); // use the default color
	}
	
	/**
	 * 	Checks whether the user has Internet connection or not, and in the latest case attempts to start it.
	 */
	private boolean initializationWifi(){
		final WifiManager wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
		//Checks if wifi connection is enabled
		if(!wifi.isWifiEnabled()){
			//Create a dialog asking whether to activate it or not
        	AlertDialog.Builder activateWifi = new AlertDialog.Builder(this);
        	activateWifi.setMessage(R.string.msgActivateWifi)
		       .setCancelable(false)
		       .setPositiveButton(R.string.msgYes, new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		        	   //Activates wifi connection
		        	   wifi.setWifiEnabled(true);
		        	   Toast.makeText(getApplicationContext(), R.string.msgSearchingWifi, Toast.LENGTH_LONG).show();   
		       		   dialog.cancel();
		       		
		           }
		       })
		       .setNegativeButton(R.string.msgNo, new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		        	    //Exits without any changes done, this will keep the map showing as a greyed layout, although all the markers will still
		        	   	//appear and will still be usable
		                dialog.cancel();
		                
		           }
		       });
		
			//Create and show the dialog
        	activateWifi.create();
        	activateWifi.show();
        	return false;
		}return true;
	}
	
	/**
     * Initialization of the location
     */
    private void initializationLocation(){
	   
    	ARLocationManager myLocationManager = new ARLocationManager(getApplicationContext());
    	myLocationManager.requestUpdates(2000, 10, locationListener);
    	Location location = myLocationManager.getLastLocation();
    	myLocation = location;

    }
    
    /**
     * Location listener
     */
	private final LocationListener locationListener = new LocationListener() {
		//When change the location call the method which update the screen with the new dates 
		public void onLocationChanged(Location location) {
			mapOverlays.clear();
			myLocation = location;
	        GeoPoint center = new GeoPoint((int)(myLocation.getLatitude()*1000000),(int)(myLocation.getLongitude()*1000000));
			mc.animateTo(center);
	    	OverlayItem item;
	    	//Current location
	        start = new GeoPoint((int)(myLocation.getLatitude()*1000000),(int)(myLocation.getLongitude()*1000000));
	        item = new OverlayItem(start, "Inici Ruta", "");
	        startManager.removeOverlays();
			startManager.addOverlay(item);
			DrawPath(start, destination, Color.GREEN, mapView);
			mapOverlays.add(startManager);
			mapOverlays.add(desitinationManager);
			startManager.draw();
			desitinationManager.draw();
		}
		
		//When position is not found
		public void onProviderDisabled(String provider){
			Toast.makeText(getApplicationContext(), "No location found", Toast.LENGTH_LONG).show();
			finish();
		}
		public void onProviderEnabled(String provider){ }
		public void onStatusChanged(String provider, int status, Bundle extras){ }
	};
	
	/**
	 * Tells whether a location service is available or not.
	 */
	private boolean isLocationAvailable(){
		String context = Context.LOCATION_SERVICE;
		LocationManager locationManager = (LocationManager)getSystemService(context);
		Criteria criteria = new Criteria();
	    criteria.setAccuracy(Criteria.ACCURACY_FINE);
	    criteria.setAltitudeRequired(false);
	    criteria.setBearingRequired(false);
	    criteria.setCostAllowed(true);
	    criteria.setPowerRequirement(Criteria.POWER_LOW );
	    String provider = locationManager.getBestProvider(criteria, true);
	    
	    if (provider != null && locationManager.isProviderEnabled(provider)) {
            // Provider is enabled
            return true;
        } else {
        	
        	//Create the location dialog
        	AlertDialog.Builder builderRestore = new AlertDialog.Builder(this);
        	//Set the location of the dialog
        	builderRestore.setMessage(R.string.msgLocation)
		       .setCancelable(false)
		       .setPositiveButton(R.string.msgYes, new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		        	   Intent settingsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
		       		startActivityForResult(settingsIntent,2);
		       		dialog.cancel();
		       		
		           }
		       })
		       .setNegativeButton(R.string.msgNo, new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		                dialog.cancel();
		                
		           }
		       });
		
			//Create and show the dialog
			builderRestore.create();
			builderRestore.show();
        	
    		
        }
	    return false;
	}
	
	//public ConnectionChangeReceiver connectionReceiver = new ConnectionChangeReceiver();

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}
	
}
